package main

import (
	"fmt"
	"math/rand"
	"runtime"
	"time"
)

//排查方法http.ListenAndServe("localhost:6060", nil))

/*
Goroutine 内正在进行 channel/mutex 等读写操作，但由于逻辑问题，某些情况下会被一直阻塞。
Goroutine 内的业务逻辑进入死循环，资源一直无法释放。
Goroutine 内的业务逻辑进入长时间等待，有不断新增的 Goroutine 进入等待。
*/
func main() {

	for i := 0; i < 4; i++ {
		queryAll()
		fmt.Printf("goroutines: %d\n", runtime.NumGoroutine())
	}
}

func queryAll() int {
	ch := make(chan int)
	for i := 0; i < 3; i++ {
		go func() { ch <- query() }()
	} //开启了三个协程，有两个协程堵塞
	return <-ch
}

func query() int {
	n := rand.Intn(100)
	time.Sleep(time.Duration(n) * time.Millisecond)
	return n
}

/*最后可看到输出的 goroutines 数量是在不断增加的，每次多 2 个。也就是每调用一次，都会泄露 Goroutine。
原因在于 channel 均已经发送了（每次发送 3 个），但是在接收端并没有接收完全（只返回 1 个 ch），所诱发的 Goroutine 泄露。*/
